package it.patterns;

import it.patterns.behavioral.chainresponsibility.ChainOfResponsibility;
import it.patterns.behavioral.chainresponsibility.ConcreteHandlerA;
import it.patterns.behavioral.chainresponsibility.ConcreteHandlerB;
import it.patterns.behavioral.chainresponsibility.ConcreteHandlerC;
import it.patterns.behavioral.command.ConcreteCommandA;
import it.patterns.behavioral.command.ConcreteCommandB;
import it.patterns.behavioral.command.ConcreteCommandC;
import it.patterns.behavioral.command.Invoker;
import it.patterns.behavioral.command.Receiver;
import it.patterns.behavioral.interpreter.AndExpression;
import it.patterns.behavioral.interpreter.BooleanExpression;
import it.patterns.behavioral.interpreter.Constant;
import it.patterns.behavioral.interpreter.Context;
import it.patterns.behavioral.interpreter.NotExpression;
import it.patterns.behavioral.interpreter.OrExpression;
import it.patterns.behavioral.interpreter.VariableExpression;
import it.patterns.behavioral.iterator.Aggregate;
import it.patterns.behavioral.iterator.ConcreteAggregate;
import it.patterns.behavioral.iterator.Iterator;
import it.patterns.behavioral.mediator.ConcreteMediator;
import it.patterns.behavioral.memento.Memento;
import it.patterns.behavioral.memento.Originator;
import it.patterns.behavioral.observer.ConcreteObserverA;
import it.patterns.behavioral.observer.ConcreteObserverB;
import it.patterns.behavioral.observer.ConcreteSubject;
import it.patterns.behavioral.observer.Observer;
import it.patterns.behavioral.strategy.StrategyA;
import it.patterns.behavioral.strategy.StrategyB;
import it.patterns.behavioral.templatemethod.ConcreteClass;
import it.patterns.behavioral.templatemethod.TemplateMethod;
import it.patterns.behavioral.visitor.ConcreteVisitor;
import it.patterns.behavioral.visitor.VisitableFloat;
import it.patterns.behavioral.visitor.VisitableString;
import it.patterns.behavioral.visitor.Visitor;

import java.util.Vector;

public class TestBehavioral {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		System.out.println("Design Patterns Test\n");

		System.out
				.println("********************************************************");
		System.out.println("Chain of Responsibility");
		System.out
				.println("********************************************************");
		ChainOfResponsibility handlerA = new ConcreteHandlerA();
		ChainOfResponsibility handlerB = new ConcreteHandlerB();
		ChainOfResponsibility handlerC = new ConcreteHandlerC();
		handlerA.setSuccessorHandler(handlerB);
		handlerB.setSuccessorHandler(handlerC);

		System.out.println(handlerA.handleRequest(0));
		System.out.println(handlerA.handleRequest(1));
		System.out.println(handlerA.handleRequest(2));

		System.out.println("\n");
		System.out
				.println("********************************************************");
		System.out.println("Command");
		System.out
				.println("********************************************************");
		Receiver receiver = new Receiver();
		Invoker invoker = new Invoker(new ConcreteCommandA(receiver),
				new ConcreteCommandB(receiver), new ConcreteCommandC(receiver));
		invoker.doCommandA();
		invoker.doCommandB();
		invoker.doCommandC();

		System.out.println("\n");
		System.out
				.println("********************************************************");
		System.out.println("Interpreter");
		System.out
				.println("********************************************************");
		VariableExpression p = new VariableExpression("p");
		VariableExpression q = new VariableExpression("q");
		System.out.println("Expression: (true AND p) OR ( q AND NOT p )");
		BooleanExpression expr = new OrExpression(new AndExpression(
				new Constant(true), p), new AndExpression(q, new NotExpression(
				p)));
		Context context = new Context();
		context.assign(p, true);
		context.assign(q, true);
		System.out.println("(p=true,q=true) The result is: "
				+ expr.evaluate(context));
		context.assign(p, true);
		context.assign(q, false);
		System.out.println("(p=true,q=false) The result is: "
				+ expr.evaluate(context));

		System.out.println("\n");
		System.out
				.println("********************************************************");
		System.out.println("Iterator");
		System.out
				.println("********************************************************");
		int size = 10;
		Aggregate<String> aggregate = new ConcreteAggregate<String>(size);
		for (int i = 0; i < size; i++) {
			try {
				aggregate.add("Element " + i, i);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		Iterator<String> it = aggregate.createIterator();
		while (!it.isDone()) {
			System.out.println(it.currentItem());
			it.next();
		}

		System.out.println("\n");
		System.out
				.println("********************************************************");
		System.out.println("Madiator");
		System.out
				.println("********************************************************");
		ConcreteMediator mediator = new ConcreteMediator();
		mediator.createCollegues();
		mediator.getcA().setData("Hello World!");
		mediator.getcB().setData(true);
		mediator.getcB().setData(false);
		mediator.getcA().setData("Hi there!");

		System.out.println("\n");
		System.out
				.println("********************************************************");
		System.out.println("Memento");
		System.out
				.println("********************************************************");
		Originator originator = new Originator();
		Memento memento = originator.createMemento();
		for (int i = 0; i < 5; i++) {
			originator.doSomeStuff(i);
			System.out.println(originator.getState());
		}
		memento.restoreState();
		System.out.println(originator.getState());
		for (int i = 0; i < 5; i++) {
			if (i == 2)
				memento = originator.createMemento();
			originator.doSomeStuff(i);
			System.out.println(originator.getState());
		}
		memento.restoreState();
		System.out.println(originator.getState());

		System.out.println("\n");
		System.out
				.println("********************************************************");
		System.out.println("Observer");
		System.out
				.println("********************************************************");
		Observer observerA = new ConcreteObserverA();
		Observer observerB = new ConcreteObserverB();
		ConcreteSubject s1 = new ConcreteSubject();
		s1.attachObserver(observerA);
		s1.attachObserver(observerB);
		for (int i = 0; i < 5; i++)
			s1.setState(i);

		System.out.println("\n");
		System.out
				.println("********************************************************");
		System.out.println("State");
		System.out
				.println("********************************************************");
		it.patterns.behavioral.state.Context stateContext = new it.patterns.behavioral.state.Context();
		stateContext.request();
		stateContext.request();
		stateContext.request();
		stateContext.request();

		System.out.println("\n");
		System.out
				.println("********************************************************");
		System.out.println("Strategy");
		System.out
				.println("********************************************************");
		it.patterns.behavioral.strategy.Context strategyContext = new it.patterns.behavioral.strategy.Context(
				10);
		for (int i = 0; i < 10; i++)
			strategyContext.setValue(i, i);

		strategyContext.setDisplayFormat(new StrategyA());
		strategyContext.display();
		strategyContext.setDisplayFormat(new StrategyB());
		strategyContext.display();

		System.out.println("\n");
		System.out
				.println("********************************************************");
		System.out.println("Template Method");
		System.out
				.println("********************************************************");
		TemplateMethod templateMethod = new ConcreteClass();
		templateMethod.templateMethod();

		System.out.println("\n");
		System.out
				.println("********************************************************");
		System.out.println("Visitor");
		System.out
				.println("********************************************************");
		// Prepare a heterogeneous collection
		Vector untidyObjectCase = new Vector();
		untidyObjectCase.add(new VisitableString("A string"));
		untidyObjectCase.add(new VisitableFloat(1));

		Vector aVector = new Vector();
		aVector.add(new VisitableString("Another string"));
		aVector.add(new VisitableFloat(2));
		untidyObjectCase.add(aVector);
		untidyObjectCase.add(new VisitableFloat(3));
		untidyObjectCase.add(new Double(4));
		// Visit the collection
		Visitor browser = new ConcreteVisitor();
		browser.visit(untidyObjectCase);
	}
}
